package com.cyz.service.impl;


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cyz.repository.UserCouponRepository;
import com.cyz.service.CouponService;
import com.cyz.service.UserCouponService;
import com.demo.mobile.MobException;
import com.demo.util.DateUtil;
import com.demo.util.JSONUtils;
import com.demo.util.MathUtil;
import com.demo.util.StringUtil;
import com.h5.Ret;
import com.vsd.daoEx.model.CouponEx;
import com.vsd.domain.Coupon;
import com.vsd.domain.UserCoupon;
import com.vsd.mobile.error.MEnumError;
import com.zy.order.proto.MSOrder.MCoupon;
import com.zy.order.proto.MSOrder.MCouponList;
import com.zy.sys.proto.MOCommon.MRet;

@Service
@Transactional
public class UserCouponServiceImpl implements UserCouponService {

	@SuppressWarnings("unused")
	private static final Logger LOGGER = LoggerFactory
			.getLogger(UserCouponServiceImpl.class);
	
	@Autowired
	JdbcTemplate jdbcTemplate;
	
	@Autowired
	private UserCouponRepository userCouponRepository;
	@Autowired
	private CouponService couponService;

	@Override
	public void save(UserCoupon coupon) {
		// TODO Auto-generated method stub
		coupon.setId(StringUtil.getUUID());
		userCouponRepository.save(coupon);
	}
	
	@Override
	public void update(UserCoupon coupon) {
		// TODO Auto-generated method stub
		userCouponRepository.save(coupon);
	}

	@Override
	public MRet.Builder adaptCoupon(String id,String userId) throws Exception{
		Coupon c = couponService.findByOne(id);
		if(c.getTotal()<=0){
			throw new MobException(MEnumError.COUPON_NOT_ENOUGH);
		}
		if(DateUtil.compareDate(c.getEndTime(), new Date())<0){
			throw new MobException(MEnumError.COUPON_OUT_OF_DATE);
		}
		//查询是否符合领取条件
		if(c.getFlag()==1){//仅能领取一次
			UserCoupon uc = userCouponRepository.findByCouponIdAndUserId(id, userId);
			if(uc!=null) throw new MobException(MEnumError.COUPON_ONLY_ONE);
		}else if(c.getFlag()==2){//每天领取一次
			UserCoupon uc = userCouponRepository.findByCouponIdAndUserIdAndCreateTimeBetween(id, userId, 
					DateUtil.strToDate(DateUtil.dateToStr(new Date(), "yyyy-MM-dd")+" 00:00:00"), 
					DateUtil.strToDate(DateUtil.dateToStr(new Date(), "yyyy-MM-dd")+" 23:59:59"));
			if(uc!=null) throw new MobException(MEnumError.COUPON_ONLY_ONE_DAY);
		}
		//用户领取
		UserCoupon co = new UserCoupon();
		co.setCouponId(c.getId());
		co.setCreateTime(new Date());
		co.setState(1);
		co.setUserId(userId);
		co.setCode(MathUtil.getRandomByTime(8));
		save(co);
		//更新优惠券数量
		couponService.updateTotal(id, 1);
		MRet.Builder ret = MRet.newBuilder();
		ret.setCode(0);
		return ret;
	}

	@Override
	public com.zy.order.proto.MSOrder.MCoupon.Builder getBestCoupont(
			String userId, String storeId, BigDecimal total,String couponId) {
		String sql = "select u.id,u.code,c.full,c.value from f_user_coupon u left join f_coupon c on c.id= u.coupon_id where u.user_id = '"
				+ userId+"' and u.state=1 and c.begin_time <= '"+DateUtil.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss")+"' and c.end_time >='"
				+DateUtil.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss")+"' order by u.create_time desc";
		List<java.util.Map<String,Object>> maps = jdbcTemplate.queryForList(sql);
		List<CouponEx> list = new ArrayList<CouponEx>();
		for (Map<String, Object> map : maps) {
			CouponEx ex = new CouponEx();
			ex.setFull(map.get("full")==null?0:new Integer(map.get("full").toString()));
			ex.setId(StringUtil.obj2String(map.get("id")));
			ex.setValue(map.get("value")==null?0:new Integer(map.get("value").toString()));
			ex.setCode(StringUtil.obj2String(map.get("code")));
			list.add(ex);
		}
		CouponEx e = getBestCoupon(storeId, total, list,couponId);
		if(e==null) return null;
		MCoupon.Builder ret = MCoupon.newBuilder();
		ret.setId(e.getId());
		ret.setCode(e.getCode());
		ret.setValue(e.getValue().toString());
		ret.setInfo(e.getFull().toString());
		return ret;
	}
	
	@Override
	public com.zy.order.proto.MSOrder.MCouponList.Builder getUsableCouponList(
			String userId, String storeId, BigDecimal total) {
		String sql = "select u.id,u.code,c.full,c.value from f_user_coupon u left join f_coupon c on c.id= u.coupon_id where u.user_id = '"
				+ userId+"' and u.state=1 and c.store_id = '"+storeId+"' and c.begin_time <= '"+DateUtil.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss")+"' and c.end_time >='"
				+DateUtil.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss")+"' order by u.create_time desc";
		List<java.util.Map<String,Object>> maps = jdbcTemplate.queryForList(sql);
		MCouponList.Builder list = MCouponList.newBuilder();
		for (Map<String, Object> map : maps) {
			MCoupon.Builder ex = MCoupon.newBuilder();
			ex.setId(StringUtil.obj2String(map.get("id")));
			ex.setCode(StringUtil.obj2String(map.get("code")));
			ex.setValue(map.get("value")==null?"0":map.get("value").toString());
			ex.setInfo(map.get("full")==null?"0":map.get("full").toString());
			list.addList(ex);
		}
		return list;
	}
	
	
	@Override
	public MCouponList.Builder getMyCoupons(
			String userId) {
		String sql = "select u.id,u.code,c.full,c.value from f_user_coupon u left join f_coupon c on c.id= u.coupon_id where u.user_id = '"
				+ userId+"' and u.state=1 and c.begin_time <= '"+DateUtil.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss")+"' and c.end_time >='"
				+DateUtil.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss")+"' order by u.create_time desc";
		List<java.util.Map<String,Object>> maps = jdbcTemplate.queryForList(sql);
		MCouponList.Builder ret = MCouponList.newBuilder();
		for (Map<String, Object> map : maps) {
			MCoupon.Builder m = MCoupon.newBuilder();
			m.setInfo(StringUtil.obj2String(map.get("full")));
			m.setId(StringUtil.obj2String(map.get("id")));
			m.setValue(StringUtil.obj2String(map.get("value")));
			m.setCode(StringUtil.obj2String(map.get("code")));
			ret.addList(m);
		}
		if(maps.size()==0) return null; 
		return ret;
	}
	
	//领取优惠券
	@Override
	public MCouponList.Builder adaptCoupon(
			String userId) {
		MCouponList.Builder ret = MCouponList.newBuilder();
		//可领取优惠券
		Collection<Coupon> list = couponService.
				findBySourceAndBeginTimeBeforeAndEndTimeAfterAndTotalGreaterThan(1, new Date(), new Date(), new Sort(Direction.DESC, "value"));
		List<UserCoupon> adaptList = new ArrayList<>();
		//查看是否能领取
		for (Coupon coupon : list) {
			int c = 0;
			if(coupon.getFlag()==1){//1仅一此
				c = userCouponRepository.countByUserIdAndCouponId(userId, coupon.getId());
			}else if(coupon.getFlag()==2){ // 2:每天1次
				String day = DateUtil.dateToStr(new Date(), "yyyy-MM-dd");
				c = userCouponRepository.countByUserIdAndCouponIdAndCreateTimeBetween(userId, coupon.getId()
						, DateUtil.strToDate(day+" 00:00:00", "yyyy-MM-dd HH:mm:ss"), DateUtil.strToDate(day+" 23:59:59", "yyyy-MM-dd HH:mm:ss"));
				 
			}else if(coupon.getFlag()==3){ //3:用完可再领'
				//是否还有未使用的
				c = userCouponRepository.countByUserIdAndCouponIdAndState(userId, coupon.getId(), 1);
			}
			if(c==0){
				UserCoupon co = new UserCoupon();
				co.setCode(StringUtil.getRandomNum(6));
				co.setCouponId(coupon.getId());
				co.setCreateTime(new Date());
				co.setId(StringUtil.getUUID());
				co.setState(1);
				co.setUserId(userId);
				adaptList.add(co);
				
				MCoupon.Builder m = MCoupon.newBuilder();
				m.setInfo(String.valueOf(coupon.getFull()));
				m.setId(co.getId());
				m.setValue(String.valueOf(coupon.getValue()));
				m.setCode(co.getCode());
				ret.addList(m);
			}
		}
		
		//插入优惠券
		userCouponRepository.save(adaptList);
		//更新优惠券库存
		if(adaptList.size()>0){
			String update = "update f_coupon c set c.total=c.total-1 where c.id in (";
			for (UserCoupon c : adaptList) {
				update+="'"+c.getCouponId()+"',";
			}
			update = update.substring(0, update.length()-1);
			update+=")";
			jdbcTemplate.execute(update);
		}
		
		return ret;
	}
	
	
	/**
	 * 商家优惠券满减匹配
	 * 
	 * @param storeId
	 * @param total
	 * @param list
	 * @return
	 * @throws Exception
	 */
	private CouponEx getBestCoupon(String storeId, BigDecimal total,
			List<CouponEx> list,String couponId) {
		if (total == null)
			return null;
		if (list == null)
			return null;
		if (StringUtils.isBlank(storeId))
			return null;

		int temp = 0;
		int k = -1;
			
		for (int i = 0; i < list.size(); i++) {
			CouponEx ex = list.get(i);
			if(StringUtils.isNotBlank(couponId)&&ex.getId().equals(couponId)){
				return ex;
			}
			Integer full = ex.getFull() == null ? 0 : ex.getFull();
			if (total.floatValue() >= full
					&& temp <= full) {
				temp = ex.getValue();
				k = i;
			}
		}

		return k == -1 ? null : list.get(k);
	}

	@Override
	public UserCoupon findById(String id) {
		// TODO Auto-generated method stub
		return userCouponRepository.findOne(id);
	}

	@Override
	public void delByCouponId(String couponId) {
		// TODO Auto-generated method stub
		String sql = "delete from f_user_coupon  where coupon_id = '"+couponId+"'";
		jdbcTemplate.execute(sql);
	}
	@Override
	public String getMyCouponList(String userId){
		String sql = "select u.id,u.code,c.full,c.value from f_user_coupon u left join f_coupon c on c.id= u.coupon_id where u.user_id = '"
				+ userId
				+ "' and u.state=1 and c.begin_time <= '"
				+ DateUtil.dateToStr(new Date(), "yyyy-MM-dd HH:mm:ss")
				+ "' and c.end_time >='"
				+ DateUtil.dateToStr(new Date(), "yyyy-MM-dd HH:mm:ss")
				+ "' order by u.create_time desc";
		List<java.util.Map<String, Object>> maps = jdbcTemplate
				.queryForList(sql);
		JSONArray ret = new JSONArray();
		for (Map<String, Object> map : maps) {
			JSONObject object = new JSONObject();
			object.put("info", map.get("full"));
			object.put("id", map.get("id"));
			object.put("value", map.get("value"));
			object.put("code", map.get("code"));
			ret.add(object);
		}
		return JSONUtils.serialize(ret);
	}
	
	@Override
	public Ret getCoupon(String id, String userId) {
		Coupon c = couponService.findByOne(id);
		if (c.getTotal() <= 0) {
			return new Ret(MEnumError.COUPON_NOT_ENOUGH);
		}
		if (DateUtil.compareDate(c.getEndTime(), new Date()) < 0) {
			return new Ret(MEnumError.COUPON_OUT_OF_DATE);
		}
		// 查询是否符合领取条件
		if (c.getFlag() == 1) {// 仅能领取一次
			UserCoupon uc = userCouponRepository.findByCouponIdAndUserId(id,
					userId);
			if (uc != null)
				return new Ret(MEnumError.COUPON_ONLY_ONE);
		} else if (c.getFlag() == 2) {// 每天领取一次
			UserCoupon uc = userCouponRepository
					.findByCouponIdAndUserIdAndCreateTimeBetween(
							id,
							userId,
							DateUtil.strToDate(DateUtil.dateToStr(new Date(),
									"yyyy-MM-dd") + " 00:00:00"),
							DateUtil.strToDate(DateUtil.dateToStr(new Date(),
									"yyyy-MM-dd") + " 23:59:59"));
			if (uc != null)
				return new Ret(MEnumError.COUPON_ONLY_ONE_DAY);
		}
		// 用户领取
		UserCoupon co = new UserCoupon();
		co.setCouponId(c.getId());
		co.setCreateTime(new Date());
		co.setState(1);
		co.setUserId(userId);
		co.setCode(MathUtil.getRandomByTime(8));
		save(co);
		// 更新优惠券数量
		couponService.updateTotal(id, 1);

		return new Ret(0);
	}
 

	
}
